﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenTK.Graphics.OpenGL;
using PixelFormat = System.Drawing.Imaging.PixelFormat;

namespace Chimp.Core
{
    public class ChimpTexture2D : ChimpTexture
    {
        public static bool[] UnitBound = new bool[256];
        private static readonly Dictionary<string, ChimpTexture2D> TexCache = new Dictionary<string, ChimpTexture2D>();

        static ChimpTexture2D()
        {
   
            for (int i = 0; i < 255; i++)
            {
                UnitBound[i] = false;
            }
        }

        public ChimpTexture2D(int width, int height)
        {
            var TextureBitmap = new Bitmap(width, height);
            //get the data out of the bitmap
            BitmapData TextureData =
                TextureBitmap.LockBits(
                    new Rectangle(0, 0, TextureBitmap.Width, TextureBitmap.Height),
                    ImageLockMode.ReadOnly,
                    PixelFormat.Format24bppRgb
                    );

            //Code to get the data to the OpenGL Driver

            GL.Enable(EnableCap.Texture2D);
            //generate one texture and put its ID number into the "Texture" variable
            GL.GenTextures(1, out Texture);
            //tell OpenGL that this is a 2D texture
            GL.BindTexture(TextureTarget.Texture2D, Texture);

            //the following code sets certian parameters for the texture
            GL.TexEnv(TextureEnvTarget.TextureEnv,
                      TextureEnvParameter.TextureEnvMode,
                      (float) TextureEnvMode.Replace);
            GL.TexParameter(TextureTarget.Texture2D,
                            TextureParameterName.TextureMinFilter,
                            (float) TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D,
                            TextureParameterName.TextureMagFilter,
                            (float) TextureMagFilter.Linear);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb32f, TextureBitmap.Width,
                          TextureBitmap.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedByte,
                          TextureData.Scan0);

            Width = TextureBitmap.Width;
            Height = TextureBitmap.Height;
            Format = TextureFormat.Rgb;

            //load the data by telling OpenGL to build mipmaps out of the bitmap data
            //.Build2DMipmap(TextureTarget.Texture2D,
            //   (int)PixelInternalFormat.Three, TextureBitmap.Width, TextureBitmap.Height,
            // PixelFormat.Bgr, PixelType.UnsignedByte,
            // TextureData.Scan0
            // );

            //free the bitmap data (we dont need it anymore because it has been passed to the OpenGL driver
            TextureBitmap.UnlockBits(TextureData);
            GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.Disable(EnableCap.Texture2D);
        }

        public ChimpTexture2D(Bitmap bitmap)
        {
            Bitmap TextureBitmap = bitmap;
            //get the data out of the bitmap
            FromBits(TextureBitmap);
        }

        public ChimpTexture2D(string path)
        {
            if (TexCache.ContainsKey(path))
            {
                ChimpTexture2D tex = TexCache[path];
                Width = tex.Width;
                Height = tex.Height;
                Texture = tex.Texture;
                Format = tex.Format;
                ImageID = tex.ImageID;
                return;
            }

            if (File.Exists(path))
            {
                
                FromBits(new Bitmap(path));
            }
            else
            {
                Environment.Exit(-1);
                FromBits(new Bitmap(64, 64));
            }
            TexCache.Add(path, this);
        }

        private void FromBits(Bitmap TextureBitmap)
        {
            /*
            Bitmap bit = new Bitmap(TextureBitmap.Width, TextureBitmap.Height);
            
            for (int x = 0; x < bit.Width; x++)
            {
                for (int y = 0; y < bit.Height; y++)
                {
                    var c = TextureBitmap.GetPixel(x, y);
                    var a = c.A;
                    var nc = Color.FromArgb(c.A, c.B, c.G, c.R);
                    bit.SetPixel(x, y, nc);

                }
            }
           
            TextureBitmap = bit;
           
             */
            BitmapData TextureData =
                TextureBitmap.LockBits(
                    new Rectangle(0, 0, TextureBitmap.Width, TextureBitmap.Height),
                    ImageLockMode.ReadOnly,
                    PixelFormat.Format32bppArgb);

            //Code to get the data to the OpenGL Driver

            GL.Enable(EnableCap.Texture2D);
            //generate one texture and put its ID number into the "Texture" variable
            GL.GenTextures(1, out Texture);
            //tell OpenGL that this is a 2D texture
            GL.BindTexture(TextureTarget.Texture2D, Texture);

            //the following code sets certian parameters for the texture
            GL.TexEnv(TextureEnvTarget.TextureEnv,
                      TextureEnvParameter.TextureEnvMode,
                      (float) TextureEnvMode.Modulate);
            GL.TexParameter(TextureTarget.Texture2D,
                            TextureParameterName.TextureMinFilter,
                            (float) TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D,
                            TextureParameterName.TextureMagFilter,
                            (float) TextureMagFilter.Linear);


            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, TextureBitmap.Width,
                          TextureBitmap.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte,
                          TextureData.Scan0);

            Width = TextureBitmap.Width;
            Height = TextureBitmap.Height;
            Format = TextureFormat.Rgba;

            //load the data by telling OpenGL to build mipmaps out of the bitmap data
            //.Build2DMipmap(TextureTarget.Texture2D,
            //   (int)PixelInternalFormat.Three, TextureBitmap.Width, TextureBitmap.Height,
            // PixelFormat.Bgr, PixelType.UnsignedByte,
            // TextureData.Scan0
            // );

            //free the bitmap data (we dont need it anymore because it has been passed to the OpenGL driver
            TextureBitmap.UnlockBits(TextureData);
            GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.Disable(EnableCap.Texture2D);
        }

        public override void Bind(int TexUnit)
        {
            UnitBound[TexUnit] = true;
            GL.ClientActiveTexture((TextureUnit) ((int) TextureUnit.Texture0 + TexUnit));
            GL.ActiveTexture((TextureUnit) ((int) TextureUnit.Texture0 + TexUnit));
            GL.Enable(EnableCap.Texture2D);
            GL.BindTexture(TextureTarget.Texture2D, Texture);
        }

        public override void Unbind(int TexUnit)
        {
            UnitBound[TexUnit] = false;
            GL.ClientActiveTexture((TextureUnit) ((int) TextureUnit.Texture0 + TexUnit));
            GL.ActiveTexture((TextureUnit) ((int) TextureUnit.Texture0 + TexUnit));
            GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.Disable(EnableCap.Texture2D);
        }
    }
}